001 /*
002 * Copyright 2005 Stephen J. McConnell
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.tools.tasks;
020
021 import java.io.File;
022
023
024 import net.dpml.tools.Context;
025 import net.dpml.tools.impl.DefaultContext;
026
027 import net.dpml.library.Library;
028 import net.dpml.library.Resource;
029 import net.dpml.library.ResourceNotFoundException;
030
031 import org.apache.tools.ant.BuildException;
032 import org.apache.tools.ant.Project;
033 import org.apache.tools.ant.Task;
034 import org.apache.tools.ant.types.FileSet;
035 import org.apache.tools.ant.taskdefs.Mkdir;
036 import org.apache.tools.ant.taskdefs.Copy;
037 import org.apache.tools.ant.taskdefs.Delete;
038 import org.apache.tools.ant.taskdefs.Checksum;
039 import org.apache.tools.ant.taskdefs.ExecTask;
040
041
042 /**
043 * Prepare the target build directory based on content presented under the
044 * ${basedir}/src and ${basedir}/etc directories.
045 *
046 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
047 * @version 1.1.1
048 */
049 public class GenericTask extends Task
050 {
051 /**
052 * Constant key for the GPG exe name.
053 */
054 public static final String GPG_EXE_KEY = "project.gpg.exe";
055
056 /**
057 * MD5 file type.
058 */
059 public static final String MD5_EXT = "md5";
060
061 /**
062 * ASC file type.
063 */
064 public static final String ASC_EXT = "asc";
065
066 private boolean m_init = false;
067
068 /**
069 * Initialize the task.
070 */
071 public void init()
072 {
073 if( !m_init )
074 {
075 super.init();
076 m_init = true;
077 }
078 }
079
080 /**
081 * Return the initialized state of the task.
082 * @return true if initialized
083 */
084 protected boolean isInitialized()
085 {
086 return m_init;
087 }
088
089 /**
090 * Get the project definition.
091 * @return the resource
092 */
093 protected Resource getResource()
094 {
095 return getContext().getResource();
096 }
097
098 /**
099 * Get the library.
100 * @return the library
101 */
102 protected Library getLibrary()
103 {
104 return getContext().getLibrary();
105 }
106
107 /**
108 * Get the project context.
109 * @return the project context
110 */
111 public Context getContext()
112 {
113 Project project = getProject();
114 Object object = project.getReference( "project.context" );
115 if( object != null )
116 {
117 if( object instanceof Context )
118 {
119 return (Context) object;
120 }
121 else
122 {
123 //System.out.println(
124 // net.dpml.lang.StandardClassLoader.toString(
125 // object.getClass().getClassLoader(),
126 // Context.class.getClassLoader() ) );
127
128 final String error =
129 "Object assigned under the 'project.context' key is not assignable to a context instance."
130 + "\nObject: " + object.getClass().getName()
131 + "\nExpecting: " + Context.class.getName();
132 throw new IllegalStateException( error );
133 }
134 }
135 else
136 {
137 // this is an Ant initiated bootstrapping of Depot (i.e. we are
138 // not using a project established via the default builder) as such
139 // we need to declare the build signature argument and construct the
140 // project context
141
142 String signature = project.getProperty( "build.signature" );
143 if( null != signature )
144 {
145 System.setProperty( "build.signature", signature );
146 }
147
148 try
149 {
150 return new DefaultContext( project );
151 }
152 catch( ResourceNotFoundException e )
153 {
154 final String message = e.getMessage();
155 final String error = "Resource not found: " + message;
156 throw new BuildException( error, e, getLocation() );
157 }
158 catch( BuildException e )
159 {
160 throw e;
161 }
162 catch( Exception e )
163 {
164 final String error =
165 "Unexpected error while attempting to construct project context.";
166 throw new RuntimeException( error, e );
167 }
168 }
169 }
170
171 /**
172 * Utility operation to create a new directory if it does not exist.
173 * @param dir the directory to create
174 */
175 protected void mkDir( final File dir )
176 {
177 final Mkdir mkdir = (Mkdir) getProject().createTask( "mkdir" );
178 mkdir.setTaskName( getTaskName() );
179 mkdir.setDir( dir );
180 mkdir.init();
181 mkdir.execute();
182 }
183
184 /**
185 * Utility operation to copy a file from a source to a destination.
186 * @param src the src file
187 * @param destination the destination file
188 * @param filtering if true apply filtering during the copy
189 * @param includes the includes specification
190 * @param excludes the excludes specification
191 */
192 protected void copy(
193 final File src, final File destination, final boolean filtering,
194 final String includes, final String excludes )
195 {
196 mkDir( destination );
197 final Copy copy = (Copy) getProject().createTask( "copy" );
198 copy.setTaskName( getTaskName() );
199 copy.setTodir( destination );
200 copy.setFiltering( filtering );
201 copy.setOverwrite( false );
202 copy.setPreserveLastModified( true );
203 final FileSet fileset = new FileSet();
204 fileset.setDir( src );
205 fileset.setIncludes( includes );
206 fileset.setExcludes( excludes );
207 copy.addFileset( fileset );
208 copy.init();
209 copy.execute();
210 }
211
212 /**
213 * Utility operation to delete a directory .
214 * @param dir the directory to delete
215 */
216 protected void deleteDir( final File dir )
217 {
218 final Delete task = (Delete) getProject().createTask( "delete" );
219 task.setTaskName( getTaskName() );
220 task.setDir( dir );
221 task.init();
222 task.execute();
223 }
224
225 /**
226 * Create an MD5 checksum file relative to the supplied file.
227 * If an [filename].md5 file exists it will be deleted and a new
228 * MD5 created.
229 *
230 * @param file the file from which a checksum signature will be generated
231 */
232 public void checksum( final File file )
233 {
234 log( "Creating md5 checksum" );
235
236 final File md5 = new File( file.toString() + "." + MD5_EXT );
237 if( md5.exists() )
238 {
239 md5.delete();
240 }
241
242 final Checksum checksum = (Checksum) getProject().createTask( "checksum" );
243 checksum.setTaskName( getTaskName() );
244 checksum.setFile( file );
245 checksum.setFileext( "." + MD5_EXT );
246 checksum.init();
247 checksum.execute();
248 }
249
250 /**
251 * Creation of an ASC signature relative to a supplied file. If a [filename].asc
252 * exists it will be deleted and recreated relative to the supplied file content.
253 *
254 * @param file the file to sign
255 */
256 public void asc( final File file )
257 {
258 final String path = Project.translatePath( file.toString() );
259 final File asc = new File( file.toString() + "." + ASC_EXT );
260 if( asc.exists() )
261 {
262 asc.delete();
263 }
264
265 String gpg = getProject().getProperty( GPG_EXE_KEY );
266 if( ( null != gpg ) && !"".equals( gpg ) )
267 {
268 log( "Creating asc signature using '" + gpg + "'." );
269 final ExecTask execute = (ExecTask) getProject().createTask( "exec" );
270
271 execute.setExecutable( gpg );
272
273 execute.createArg().setValue( "-a" );
274 execute.createArg().setValue( "-b" );
275 execute.createArg().setValue( "-o" );
276 execute.createArg().setValue( path + "." + ASC_EXT );
277 execute.createArg().setValue( path );
278
279 execute.setDir( getProject().getBaseDir() );
280 execute.setSpawn( false );
281 execute.setAppend( false );
282 execute.setTimeout( new Integer( TIMEOUT ) );
283 execute.execute();
284 }
285 }
286
287 private static final int TIMEOUT = 10000;
288 }